﻿using Algorithm.Check;
using Common;
using HslCommunication;
using HslCommunication.Core;
using HslCommunication.Core.Pipe;
using HslCommunication.ModBus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Algorithm.Check.ExtensionForCRC16;

namespace NewDevice.RS485
{
    /// <summary>
    /// RU电源
    /// </summary>
    public class RU_12_3040_V2
    {
        private SerialBase_V2 _sb;
        private readonly ModbusRtu _modbusRtu;// http://www.hsltechnology.cn:7900/Doc/HslCommunication

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="station"></param>
        /// <param name="pipe"></param>
        public RU_12_3040_V2(byte station, SerialBase_V2 pipe)
        {
            _sb = pipe;
            _modbusRtu = new ModbusRtu();
            _modbusRtu.Station = station;
            _modbusRtu.DataFormat = DataFormat.ABCD;
            _modbusRtu.IsClearCacheBeforeRead = false;
            _modbusRtu.CommunicationPipe = pipe;
        }

        /// <summary>
        /// 设备描述
        /// </summary>
        public string DeviceDescription { get; set; } = "RU系列程控电源";

        /// <summary>
        /// 设置输出电压
        /// </summary>
        /// <param name="vol">电压值(单位：V)</param>
        /// <exception cref="Exception">当设置失败或返回数据异常时抛出</exception>
        public void SetVoltage(double vol)
        {
            short volSet = (short)(vol * 100);
            int address = 0x95;
            OperateResult writeResult;
            lock (_sb.Locker)
            {
                writeResult = _modbusRtu.Write($"x=06,{address}", volSet);
                Thread.Sleep(_sb.Delay);
            }
            if (!writeResult.IsSuccess)
            {
                throw new Exception($"写入数据失败: {writeResult.Message}");
            }
        }

        /// <summary>
        /// 读取当前输出电压
        /// </summary>
        /// <returns>当前输出电压值(单位：V)</returns>
        /// <exception cref="Exception">当读取失败或返回数据异常时抛出</exception>
        public double GetVoltage()
        {
            int address = 0x95;

            OperateResult<ushort> readResult;
            lock (_sb.Locker)
            {
                readResult = _modbusRtu.ReadUInt16($"{address}");
                Thread.Sleep(_sb.Delay);
            }

            if (!readResult.IsSuccess)
            {
                throw new Exception($"读取数据失败: {readResult.Message}");
            }
            return readResult.Content / 100.0;
        }

        /// <summary>
        /// 设置输出电流
        /// </summary>
        /// <param name="current">电流值(单位：A)</param>
        /// <exception cref="Exception">当设置失败或返回数据异常时抛出</exception>
        public void SetCurrent(double current)
        {
            short currentSet = (short)(current * 100);
            int address = 0x96;

            OperateResult writeResult;
            lock (_sb.Locker)
            {
                writeResult = _modbusRtu.Write($"x=06,{address}", currentSet);
                Thread.Sleep(_sb.Delay);
            }

            if (!writeResult.IsSuccess)
            {
                throw new Exception($"写入数据失败: {writeResult.Message}");
            }
        }

        /// <summary>
        /// 读取当前输出电流
        /// </summary>
        /// <returns>当前输出电流值(单位：A)</returns>
        /// <exception cref="Exception">当读取失败或返回数据异常时抛出</exception>
        public double GetCurrent()
        {
            int address = 0x96;

            OperateResult<ushort> readResult;
            lock (_sb.Locker)
            {
                readResult = _modbusRtu.ReadUInt16($"{address}");
                Thread.Sleep(_sb.Delay);
            }

            if (!readResult.IsSuccess)
            {
                throw new Exception($"读取数据失败: {readResult.Message}");
            }
            return readResult.Content / 100.0;
        }

        /// <summary>
        /// 测量输出电压
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public double MeasVoltage()
        {
            int address = 0x64;

            OperateResult<ushort> readResult;
            lock (_sb.Locker)
            {
                readResult = _modbusRtu.ReadUInt16($"x=4;{address}");
                Thread.Sleep(_sb.Delay);
            }

            if (!readResult.IsSuccess)
            {
                throw new Exception($"读取数据失败: {readResult.Message}");
            }
            return readResult.Content / 100.0;
        }

        /// <summary>
        /// 测量输出电流
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public double MeasCurrent()
        {
            int address = 0x65;

            OperateResult<ushort> readResult;
            lock (_sb.Locker)
            {
                readResult = _modbusRtu.ReadUInt16($"x=4;{address}");
                Thread.Sleep(_sb.Delay);
            }

            if (!readResult.IsSuccess)
            {
                throw new Exception($"读取数据失败: {readResult.Message}");
            }
            return readResult.Content / 100.0;
        }

        /// <summary>
        /// 设置电源输出状态
        /// </summary>
        /// <param name="isOn">true:开启输出, false:关闭输出</param>
        /// <exception cref="Exception">当设置失败或返回数据异常时抛出</exception>
        public void SetStatus(bool isOn)
        {
            int address = 0x85;

            OperateResult writeResult;
            lock (_sb.Locker)
            {
                writeResult = _modbusRtu.Write($"{address}", isOn);
                Thread.Sleep(_sb.Delay);
            }

            if (!writeResult.IsSuccess)
            {
                throw new Exception($"写入数据失败: {writeResult.Message}");
            }
        }
    }
}